#include "tcpmgr.h"
#include <QAbstractSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include "usermgr.h"
#include <QDebug>

TcpMgr::~TcpMgr()
{

}

TcpMgr::TcpMgr()
    :_b_recv_pending(false)
    ,_message_id(0)
    ,_message_len(0)
{
    connect(&_socket,&QTcpSocket::connected,this,[&](){
        qDebug()<<"连接成功";
        emit sig_con_success(true);
    });

//    connect(&_socket,&QTcpSocket::readyRead,this,[&](){
//       qDebug()<<"收到了数据";
//       _buffer = _socket.readAll();
//       qDebug()<<"buffer的总长度"<<_buffer.size();
//       QDataStream stream(&_buffer, QIODevice::ReadOnly);
//       stream.setVersion(QDataStream::Qt_5_0);
//       while(true)
//       {
//           //先解析头部
//           if(!_b_recv_pending)
//           {
//               if(_buffer.size()<static_cast<int>(sizeof(quint16)*2)){
//                    return;
//               }
//               stream>>_message_id>>_message_len;
//               _buffer = _buffer.mid(sizeof(quint16)*2);
//               qDebug()<<"要去掉的长度:"<<sizeof(quint16)*2;
//               //至此 头部解析完毕
//               _b_recv_pending = true;
//               qDebug()<<"message id:"<<_message_id<<" message len:"<<_message_len;
//           }
//           qDebug()<<"去掉头部之后buffer的长度:"<<_buffer.size();

//           if(_buffer.size()<_message_len){
//               qDebug()<<"buffer_size:"<<_buffer.size()<<"message_len:"<<_message_len;
//               _b_recv_pending = true;
//               return;
//           }
//           qDebug()<<"头部解析完毕 开始解析数据部分";
//           //开始解析数据部分
//           _b_recv_pending = false;
//           QByteArray message = _buffer.mid(0,_message_len);
//           qDebug()<<"message:"<<message;
//           handleMsg(ReqId(_message_id),_message_len,message);
//       }
//    });

    connect(&_socket, &QTcpSocket::readyRead, this, [this]() { // 注意：用[this]替代[&]避免潜在悬垂引用
        // 1. 追加新数据到缓冲区（不要覆盖旧数据）
        _buffer.append(_socket.readAll());

        QDataStream stream(&_buffer, QIODevice::ReadOnly);
        stream.setVersion(QDataStream::Qt_5_0);

        while (true) { // 只处理完整包，避免阻塞事件循环
            // 2. 处理消息头部
            if (!_b_recv_pending) {
                // 检查头部是否完整（id + len 共4字节）
                if (_buffer.size() < static_cast<int>(sizeof(quint16) * 2)) {
                    break; // 头部不完整，等待更多数据
                }

                // 读取头部信息（不移动缓冲区）
                stream >> _message_id >> _message_len;
                qDebug() << "Header parsed - ID:" << _message_id << "Len:" << _message_len;

                _b_recv_pending = true;
            }

            // 3. 处理消息体
            const int headerSize = sizeof(quint16) * 2;
            const int totalRequired = headerSize + _message_len;

            if (_buffer.size() < totalRequired) {
                qDebug() << "Waiting body data. Current:" << (_buffer.size() - headerSize)
                         << "/ Required:" << _message_len;
                break; // 数据体不完整，保留头部信息
            }

            // 4. 提取完整数据包
            QByteArray message = _buffer.mid(headerSize, _message_len);
            handleMsg(ReqId(_message_id), _message_len, message);

            // 5. 从缓冲区移除已处理数据
            _buffer.remove(0, totalRequired);
            _b_recv_pending = false;

            // 6. 重置流位置以处理后续数据
            stream.device()->seek(0);
        }

        qDebug() << "Remaining buffer size:" << _buffer.size();
    });

    //处理错误
    QObject::connect(&_socket, static_cast<void (QTcpSocket::*)(QTcpSocket::SocketError)>(&QTcpSocket::error),
                                [&](QTcpSocket::SocketError socketError) {
                   qDebug() << "Error:" << _socket.errorString() ;
                   switch (socketError) {
                       case QTcpSocket::ConnectionRefusedError:
                           qDebug() << "Connection Refused!";
                           emit sig_con_success(false);
                           break;
                       case QTcpSocket::RemoteHostClosedError:
                           qDebug() << "Remote Host Closed Connection!";
                           break;
                       case QTcpSocket::HostNotFoundError:
                           qDebug() << "Host Not Found!";
                           emit sig_con_success(false);
                           break;
                       case QTcpSocket::SocketTimeoutError:
                           qDebug() << "Connection Timeout!";
                           emit sig_con_success(false);
                           break;
                       case QTcpSocket::NetworkError:
                           qDebug() << "Network Error!";
                           break;
                       default:
                           qDebug() << "Other Error!";
                           break;
                   }
             });
    //处理连接断开
    connect(&_socket,&QTcpSocket::disconnected,this,[&](){
       qDebug()<<"Disconnected form server";
    });
    //处理发送信号用来发送数据
    connect(this,&TcpMgr::sig_send_data,this,&TcpMgr::slot_send_data);
    //注册回调函数
    initHandlers();
}

void TcpMgr::initHandlers()
{
    _handlers.insert(ID_CHAT_LOGIN_RSP,[&](ReqId id,int len,QByteArray data){
        qDebug()<<"id is "<<id<<"data is "<<data;
        QJsonDocument jsondoc = QJsonDocument::fromJson(data);
        //检查是否转换成功
        if(jsondoc.isNull()){
           qDebug() << "Failed to create QJsonDocument.";
           return;
        }
        QJsonObject jsonobj = jsondoc.object();
        if(!jsonobj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug()<<"login failed err is Json Rarse Err"<<err;
            emit sig_login_failed(err);
        }
        int err = jsonobj["error"].toInt();
        if(err!=ErrorCodes::SUCCESS){
            qDebug()<<"login failed err is "<<err;
            emit sig_login_failed(err);
            return;
        }

//        UserMgr::GetInstance()->SetUid(jsonobj["uid"].toInt());
//        UserMgr::GetInstance()->SetName(jsonobj["name"].toString());
//        UserMgr::GetInstance()->SetToken(jsonobj["token"].toString());
        auto uid = jsonobj["uid"].toInt();
        auto name = jsonobj["name"].toString();
        auto nick = jsonobj["nick"].toString();
        auto icon = jsonobj["icon"].toString();
        auto sex = jsonobj["sex"].toInt();

        auto user_info = std::make_shared<UserInfo>(uid,name,nick,icon,sex);
        UserMgr::GetInstance()->SetUserInfo(user_info);
        UserMgr::GetInstance()->SetToken(jsonobj["token"].toString());
        //添加申请列表
        if(jsonobj.contains("apply_list")){
            UserMgr::GetInstance()->AppendApplyList(jsonobj["apply_list"].toArray());
        }
        //添加好友列表
        if(jsonobj.contains("friend_list")){
            UserMgr::GetInstance()->AppendFriendList(jsonobj["friend_list"].toArray());
        }
        emit sig_swich_chatdlg();
    });

    _handlers.insert(ID_SEARCH_USER_RSP, [this](ReqId id, int len, QByteArray data) {
            Q_UNUSED(len);
            qDebug() << "handle id is " << id << " data is " << data;
            // 将QByteArray转换为QJsonDocument
            QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
            // 检查转换是否成功
            if (jsonDoc.isNull()) {
                qDebug() << "Failed to create QJsonDocument.";
                return;
            }
            QJsonObject jsonObj = jsonDoc.object();
            if (!jsonObj.contains("error")) {
                int err = ErrorCodes::ERR_JSON;
                qDebug() << "Login Failed, err is Json Parse Err" << err;

                emit sig_user_search(nullptr);
                return;
            }
            int err = jsonObj["error"].toInt();
            if (err != ErrorCodes::SUCCESS) {
                qDebug() << "Login Failed, err is " << err;
                emit sig_user_search(nullptr);
                return;
            }
           auto search_info =  std::make_shared<SearchInfo>(jsonObj["uid"].toInt(), jsonObj["name"].toString(),
                jsonObj["nick"].toString(), jsonObj["desc"].toString(),
                   jsonObj["sex"].toInt(), jsonObj["icon"].toString());

            emit sig_user_search(search_info);
            });
    _handlers.insert(ID_ADD_FRIEND_RSP,[this](ReqId id,int len,QByteArray data){
        Q_UNUSED(len);
        qDebug()<<"hanle id is "<<id<<"data is "<<data;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        //检查是否转换成功
        if(jsonDoc.isNull()){
            qDebug()<<"failed to create QJsonDocument";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug()<<"Add friend failed,err is Json Parse err:"<<err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug()<<"Add Friend failed err is "<<err;
            return;
        }
        qDebug()<<"add friend success";
    });

    _handlers.insert(ID_NOTIFY_ADD_FRIEND_REQ,[this](ReqId id,int len,QByteArray data){
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "Login Failed, err is Json Parse Err" << err;

            emit sig_user_search(nullptr);
            return;
        }

        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "Login Failed, err is " << err;
            emit sig_user_search(nullptr);
            return;
        }

        int from_uid = jsonObj["applyuid"].toInt();
        QString name = jsonObj["name"].toString();
        QString desc = jsonObj["desc"].toString();
        QString icon = jsonObj["icon"].toString();
        QString nick = jsonObj["nick"].toString();
        int sex = jsonObj["sex"].toInt();

        auto apply_info = std::make_shared<AddFriendApply>(from_uid,name,desc,icon,nick,sex);
        emit sig_friend_apply(apply_info);
    });
    _handlers.insert(ID_NOTIFY_AUTH_FRIEND_REQ, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }

        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "Auth Friend Failed, err is " << err;
            return;
        }

        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "Auth Friend Failed, err is " << err;
            return;
        }

        int from_uid = jsonObj["fromuid"].toInt();
        QString name = jsonObj["name"].toString();
        QString nick = jsonObj["nick"].toString();
        QString icon = jsonObj["icon"].toString();
        int sex = jsonObj["sex"].toInt();

        auto auth_info = std::make_shared<AuthInfo>(from_uid,name,
                                                    nick, icon, sex);

        emit sig_add_auth_friend(auth_info);
    });

    _handlers.insert(ID_AUTH_FRIEND_RSP, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "Auth Friend Failed, err is Json Parse Err" << err;
            return;
        }

        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "Auth Friend Failed, err is " << err;
            return;
        }

        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto uid = jsonObj["uid"].toInt();
        auto rsp = std::make_shared<AuthRsp>(uid, name, nick, icon, sex);
        emit sig_auth_rsp(rsp);

        qDebug() << "Auth Friend Success " ;
    });

    _handlers.insert(ID_TEXT_CHAT_MSG_RSP,[this](ReqId id,int len,QByteArray data){
       Q_UNUSED(len);
       qDebug()<<"handle id is "<<id<<" data is "<<data;
       QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
       //检查转换是否成功
       if(jsonDoc.isNull()){
           qDebug()<<"faiied to create QJsonDocument";
           return;
       }
       QJsonObject jsonObj = jsonDoc.object();
       if(!jsonObj.contains("error")){
           int err = ErrorCodes::ERR_JSON;
           qDebug()<<"Chat Msg Rsp Failed,err is Json Parse Err"<<err;
           return;
       }
       int err = jsonObj["error"].toInt();
       if(err != ErrorCodes::SUCCESS){
           qDebug()<<"Chat Msg Rsp Failed,err is "<<err;
           return;
       }
       qDebug()<<"Recerive Text Chat Rsp Success";
       //设置送达标记 to do...
    });
    _handlers.insert(ID_NOTIFY_TEXT_CHAT_MSG_REQ,[this](ReqId id,int len,QByteArray data){
        Q_UNUSED(len);
        qDebug()<<"收到了信息";
        qDebug()<<"hanlde id is "<<id<<" data is "<<data;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        if(jsonDoc.isNull()){
            qDebug()<<"failed to create QJsonDocument";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug()<<"Notify Chat Msg Failed,err is Json Parse Err"<<err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug()<<"Notify Chat Msg Failed,err is "<<err;
            return;
        }
        qDebug()<<"Receive text chat notify success";

        std::shared_ptr<TextChatMsg> msg_ptr = nullptr;
        //包含text_array是通过grpc发的 不包含则是直接发过来的(different)
        if(jsonObj.contains("text_array")){
            QJsonArray textarray = jsonObj["text_array"].toArray();
            QJsonValue firstElementValue = textarray.at(0);
            if(!firstElementValue.isObject()){
                qDebug()<<"text_array 的第一个元素不是对象";
                return;
            }
            QJsonObject firstElement = firstElementValue.toObject();
            if(!firstElement.contains("content")){
                qDebug()<<"content 字段不存在";
                return;
            }
            QString text = firstElement["content"].toString();
            qDebug()<<"发送过来的信息是:"<<text;
            msg_ptr = std::make_shared<TextChatMsg>(jsonObj["fromuid"].toInt(),
                                    jsonObj["touid"].toInt(),text);
        }else{
            msg_ptr = std::make_shared<TextChatMsg>(jsonObj["fromuid"].toInt(),
                                    jsonObj["touid"].toInt(),jsonObj["text"].toString());
        }
        emit sig_text_chat_msg(msg_ptr);
    });
}

void TcpMgr::handleMsg(ReqId id, int len, QByteArray data)
{
    auto iter = _handlers.find(id);
    if(iter == _handlers.end()){
        qDebug()<<"TcpMgr::handleMsg:can not find the id";
        return;
    }
    iter.value()(id,len,data);
}

void TcpMgr::slot_tcp_connect(ServerInfo si)
{
    qDebug()<<"receive tcp connect sigal";
    _host = si.host;
    _port = static_cast<uint16_t>(si.port.toUInt());
    qDebug()<<si.host<<' '<<_port;
    _socket.connectToHost(_host,_port);
}

void TcpMgr::slot_send_data(ReqId reqId, QByteArray dataBytes)
{
    uint16_t id = reqId;
    // 计算长度（使用网络字节序转换）
    quint16 len = static_cast<quint16>(dataBytes.length());
    // 创建一个QByteArray用于存储要发送的所有数据
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    // 设置数据流使用网络字节序
    out.setByteOrder(QDataStream::BigEndian);
    // 写入ID和长度
    out << id << len;
    // 添加字符串数据
    block.append(dataBytes);
    // 发送数据
    _socket.write(block);
    qDebug() << "tcp mgr send byte data is " << block ;
}
